from DoublyLink import *


class PositionalList(DoublyLink):
    """基于链表带有位置信息的列表"""

    # ----------------------------位置类------------------------------
    class Position:
        """表示一个元素位置的类"""

        def __init__(self, container, node):
            self.container = container
            self._node = node

        def element(self):
            return self._node.element

        def __eq__(self, other):
            return type(self) == type(other) and other._node == self._node

        def __ne__(self, other):
            return not (self == other)

    # ----------------------------公共方法------------------------------
    def validate(self, p):
        """内部方法，用于检查p是否合格位置对象，当位置错误时抛出异常,并返回位置节点"""
        if not isinstance(p, self.Position):
            raise TypeError('p不是一个位置类型')
        if p.container is not self:
            raise ValueError('位置p不属于此对象')
        if p._node.next is None:
            raise ValueError('p is no longer valid')
        return p._node

    def make_position(self, node):
        if node is self.header or node is self.trailer:
            return None
        else:
            return self.Position(self, node)

    # ------------------------------方法---------------------------------
    def first(self):
        return self.make_position(self.header.next)

    def last(self):
        return self.make_position(self.trailer.prev)

    def before(self, p):
        node = self.validate(p)
        return self.make_position(node.prev)

    def after(self, p):
        node = self.validate(p)
        return self.make_position(node.next)

    def __iter__(self):
        cursor = self.first()
        while cursor is not None:
            yield cursor
            cursor = self.after(cursor)

    def __reversed__(self):
        cursor = self.last()
        while cursor is not None:
            yield cursor
            cursor = self.before(cursor)

    # --------------------------外部接口-----------------------------
    # 重写继承方法,来对位置进行操作而不是节点、返回位置信息而不是节点对象
    def insert_between(self, data, prev, next_):
        """该方法为重写后，内部方法"""
        node = super().insert_between(data, prev, next_)
        return self.make_position(node)

    def add_first(self, data):
        return self.insert_between(data, self.header, self.header.next)

    def add_last(self, data):
        return self.insert_between(data, self.trailer.prev, self.trailer)

    def add_before(self, p, data):
        p_node = self.validate(p)
        return self.insert_between(data, p_node.prev, p_node)

    def add_after(self, p, data):
        p_node = self.validate(p)
        return self.insert_between(data, p_node, p_node.next)

    def delete(self, p):
        p_node = self.validate(p)
        return self.del_node(p_node)

    def replace(self, p, data):
        p_node = self.validate(p)
        old_data = p_node.element
        p_node.element = data
        return old_data

    def move_to_front(self, p):
        """通过重新链接将p移动到first"""
        p_node = self.validate(p)
        first_node = self.first()._node
        if p_node != first_node and not self.is_empty():
            first_next = first_node.next
            p_prev = p_node.prev
            p_next = p_node.next
            if first_next == p_node:
                p_node.prev, first_node.prev = self.header, p_node
                p_node.next, first_node.next = first_node, p_node.next

                self.header.next = p_node
                p_next.prev = first_node
            else:
                p_node.prev, first_node.prev = self.header, p_node.prev
                p_node.next, first_node.next = first_node.next, p_node.next

                self.header.next = p_node
                first_next.prev = p_node
                p_prev.next = first_node
                p_next.prev = first_node
        else:
            pass

    # def find(self, data):
    #     """类似find函数"""
    #     if self.size:
    #         current_node = self.header.next
    #         while current_node.element is not None:
    #             if data == current_node.element:
    #                 return self.make_position(current_node)
    #             current_node = current_node.next


if __name__ == '__main__':
    L = PositionalList()
    # for i in range(10):
    #     L.add_first(i)
    L.add_first('A')
    print(L)

    # L.move_to_front(L.after(L.first()))
    print(L)
    # print(L.max())
